# -*- coding: utf-8 -*-
import cv2
import pyzbar.pyzbar as pyzbar
import numpy as np
import sign_in
import PyQt5.QtWidgets as qw
import PyQt5.QtCore as qc
import PyQt5.QtGui as qg
import logging
import threading
import pymysql
import datetime

class Sign_In(qw.QWidget, sign_in.Ui_Form):   #创建主界面类
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        # OpenCV
        self.cap = cv2.VideoCapture()

        # 图像捕获
        self.isExternalCameraUsed = 0  # 0为不使用外接摄像头，1为使用外接摄像头
        self.cam_status = 0  # 0未未打开摄像头
        self.checkBox_external.stateChanged.connect(self.checkBox_external_cb)
        self.btn_open_camera.clicked.connect(self.startWebcam)

        # 定时器
        self.timer = qc.QTimer(self)
        self.timer.timeout.connect(self.updateFrame)

        # 是否已签退
        self.sign_back = 1
        self.back_dect = {}
        self.sign_succee = []


    def checkBox_external_cb(self):  # 设置外接摄像头chekBox槽函数
        if self.checkBox_external.isChecked():
            self.isExternalCameraUsed = 1
        else:
            self.isExternalCameraUsed = 0

    # 打开/关闭摄像头
    def startWebcam(self):
        if (self.cam_status == 0):
            self.cam_status = 1
            if (self.isExternalCameraUsed == 1):
                camID = 1
            else:
                camID = 0
            self.cap.open(camID)
            self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 641)  # 设置图像宽度
            self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 501)  # 设置图像高度
            ret, frame = self.cap.read()
            # print(ret)
            if not ret:
                logging.error('无法调用电脑摄像头{}'.format(camID))
                self.logQueue.put('Error：初始化摄像头失败')
                self.cap.release()
                self.btn_open_camera.setChecked(False)
            else:
                self.btn_open_camera.setText('关闭摄像头')
                self.timer.start(5)
        else:
            if self.cap.isOpened():
                if self.timer.isActive():
                    self.timer.stop()
                self.cap.release()
                self.label.clear()
                self.label.setText('<font color=red>未开启检测</font>')
                self.btn_open_camera.setText('开启摄像头')

    # 定时器，实时更新画面
    def updateFrame(self):
        ret, frame = self.cap.read()
        # self.image = cv2.flip(self.image, 1)
        if ret:
            self.displayImage(frame)
            self.decodeDisplay(frame)


    # 显示图像
    def displayImage(self, img):
        # BGR -> RGB
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # default：The image is stored using 8-bit indexes into a colormap， for example：a gray image
        qformat = qg.QImage.Format_Indexed8

        if len(img.shape) == 3:  # rows[0], cols[1], channels[2]
            if img.shape[2] == 4:
                # The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8)
                # A: alpha channel，不透明度参数。如果一个像素的alpha通道数值为0%，那它就是完全透明的
                qformat = qg.QImage.Format_RGBA8888
            else:
                qformat = qg.QImage.Format_RGB888

        # img.shape[1]：图像宽度width，img.shape[0]：图像高度height，img.shape[2]：图像通道数
        # QImage.__init__ (self, bytes data, int width, int height, int bytesPerLine, Format format)
        # 从内存缓冲流获取img数据构造QImage类
        # img.strides[0]：每行的字节数（width*3）,rgb为3，rgba为4
        # strides[0]为最外层(即一个二维数组所占的字节长度)，strides[1]为次外层（即一维数组所占字节长度），strides[2]为最内层（即一个元素所占字节长度）
        # 从里往外看，strides[2]为1个字节长度（uint8），strides[1]为3*1个字节长度（3即rgb 3个通道）
        # strides[0]为width*3个字节长度，width代表一行有几个像素

        outImage = qg.QImage(img, img.shape[1], img.shape[0], img.strides[0], qformat)
        self.label.setPixmap(qg.QPixmap.fromImage(outImage))
        self.label.setScaledContents(True)


    def decodeDisplay(self,video):
        # 转为灰度图像
        gray = cv2.cvtColor(video, cv2.COLOR_BGR2GRAY)
        # cv2.imshow("gray", gray)
        barcodes = pyzbar.decode(gray)  # 二维码解析的信息

        for barcode in barcodes:
            # 提取二维码的位置,然后用边框标识出来在视频中
            (x, y, w, h) = barcode.rect
            cv2.rectangle(video, (x, y), (x + w, y + h), (0, 255, 0), 2)
            # 字符串转换
            barcodeData = barcode.data.decode("utf-8")  # 二维码的data信息
            barcodeType = barcode.type
            # 在图像上面显示识别出来的内容
            text = "{}".format(barcodeData)
            cv2.putText(video, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

            # 打印识别后的内容
            print("[扫描结果] 二维码类别： {0} 内容： {1}".format(barcodeType, barcodeData))
            print(barcodeData)
            # print(barcodeData[9:13])
            try:
                self.connection = pymysql.connect(host='localhost', port=3306, user='root', passwd='123123',
                                                  database='students',
                                                  charset='utf8')
                print('successfully connect')
                self.cur = self.connection.cursor()
                sql1 = "select * from pes_show where 工号 = '" + barcodeData + "'"
                self.cur.execute(sql1)
                total = self.cur.fetchall()
                date = datetime.datetime.now().strftime('[%Y/%m/%d]')
                time = datetime.datetime.now().strftime('[%Y/%m/%d %H:%M:%S]')
                if total != "":
                    if barcodeData in self.sign_succee:
                        sql2 = "update sign_in set 签退时间= '" + time + "'WHERE 工号 = '" + barcodeData + "'" \
                                                                " and 签到时间 = '" + self.back_dect[barcodeData] + "'"
                        self.cur.execute(sql2)
                        self.sign_back = 0
                        self.sign_succee.remove(barcodeData)
                        tips = '<font color=blue>{}</font> 签退成功。'.format(total[0][1])
                        qw.QMessageBox.information(self, "提示", tips)
                    try:
                        sql = "INSERT INTO sign_in(日期,工号,姓名,签到时间) VALUES ('" + date + "', '" + barcodeData + "', '" + total[0][1] + "','" + time + "')"
                        self.cur.execute(sql)
                        self.back_dect[barcodeData] = time
                        self.sign_succee.append(barcodeData)
                        tips = '<font color=blue>{}</font> 签到成功。'.format(total[0][1])
                        qw.QMessageBox.information(self, "提示", tips)
                    except:
                        qw.QMessageBox.warning(self,"警告","您今日已签到！")
                        logging.error("已签到")

                    self.connection.commit()  # 事务的提交
                    self.cur.close()
                    self.connection.close()
                else:
                    tips = '工号<font color=blue>{}</font> 暂未录入系统。'.format(barcodeData)
                    qw.QMessageBox.information(self, "提示", tips)
            except:
                logging.error("数据库出错！")

